-- -- Copyright 2014 Alessandro Gerlinger Romero -- -- This file is part of Hybrid fUML. -- -- Hybrid fUML is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- Hybrid fUML is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with Hybrid fUML. If not, see . -- ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- APPROACH -- explicity model hybrid clock -- with reaction time, physical time and logical time -- -- ACCORDING MARTE -- IMPORTANT - parser is very simple... it is not in the hard part... however, it should parse the basic elements to allow evaluation of the semantics -- FULLY EMBEDDED ------------------------------------------------------------- -- -- derived function in the meta-model function_Clock_currentTime :: FUML_Semantics_Extensions_Clock_Clock -> Float function_Clock_currentTime c = function_fUML_currentTimeFloat (function_Clock_timeBase c) -- -- defined by symmetric relation, otherwise it was not possible because it would always cause inconsistent updates in the ASM -- -- ATTENTION: it relies on the Ord defined for the DOM function_TimeBase_instants :: FUML_Semantics_Extensions_Clock_TimeBase -> [FUML_Semantics_Extensions_Clock_Instant] function_TimeBase_instants tb = filter (\i -> (function_Instant_tb i) == tb ) $ expr2list $ dom function_Instant_tb function_MultipleTimeBase_ownedTBs :: FUML_Semantics_Extensions_Clock_MultipleTimeBase -> {FUML_Semantics_Extensions_Clock_TimeBase} function_MultipleTimeBase_ownedTBs mtb = mkSet $ filter (\tb -> (function_TimeBase_owningMTB tb) == mtb ) $ expr2list $ dom function_TimeBase_owningMTB function_Locus_logicalClocks :: FUML_Semantics_Loci_LociL1_Locus -> {FUML_Semantics_Extensions_Clock_Clock} function_Locus_logicalClocks l = mkSet $ filter (\clk -> (function_Clock_LogicalClock_locus clk) == l ) $ expr2list $ dom function_Clock_LogicalClock_locus -- -- ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- HELP FUNCTIONs function_fUML_currentTimeFloat :: FUML_Semantics_Extensions_Clock_TimeBase -> Float function_fUML_currentTimeFloat tb = function_Instant_date $ function_TimeBase_currentInstant tb function_fUML_currentTimeInt :: FUML_Semantics_Extensions_Clock_TimeBase -> Int function_fUML_currentTimeInt tb = truncate $ function_Instant_date $ function_TimeBase_currentInstant tb function_fUML_Clock_currentTimeInt :: FUML_Semantics_Extensions_Clock_Clock -> Int function_fUML_Clock_currentTimeInt c = function_fUML_currentTimeInt (function_Clock_timeBase c) function_fUML_Clock_currentTimeFloat :: FUML_Semantics_Extensions_Clock_Clock -> Float function_fUML_Clock_currentTimeFloat c = function_fUML_currentTimeFloat (function_Clock_timeBase c) -- -- used to check if a clock evolve during one reaction function_fUML_Clock_isDesynchronized :: FUML_Semantics_Extensions_Clock_Clock -> Bool function_fUML_Clock_isDesynchronized c = function_TimeBase_currentInstant(function_Clock_timeBase c) /= last (function_TimeBase_instants (function_Clock_timeBase c)) ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- EVENT -- EVENT used by the semantics function_Instance_Event_semanticEventForReactionClk ::FUML_Syntax_CommonBehaviors_Communications_Event function_Instance_Event_semanticEventForReactionClk = FUML_Syntax_CommonBehaviors_Communications_Event "reactionClk" "reactionClk" FUML_Syntax_Classes_Kernel_VisibilityKind_public FUML_Syntax_Classes_Kernel_VisibilityKind_public FUML_Syntax_Classes_Kernel_ClassifierEmpty FUML_Syntax_CommonBehaviors_Communications_SignalEvent -- EVENT used by the semantics function_Instance_Event_semanticEventForLogicalClk ::FUML_Syntax_CommonBehaviors_Communications_Event function_Instance_Event_semanticEventForLogicalClk = FUML_Syntax_CommonBehaviors_Communications_Event "logicalClk" "logicalClk" FUML_Syntax_Classes_Kernel_VisibilityKind_public FUML_Syntax_Classes_Kernel_VisibilityKind_public FUML_Syntax_Classes_Kernel_ClassifierEmpty FUML_Syntax_CommonBehaviors_Communications_SignalEvent ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- BASIC PARSER FUNCTIONS FOR CCSL -- OBS: ONLY TO SUPPORT EVALUATION OF THE SEMANTICS -- -- -- look for a CCSL that has the reactionClk and the physicalClk -- it covers models that does not model a explicit signal -- this patter is expected: -- Clock c; c isPeriodicOn physicalClk period ; c = ; function_fUML_Clock_getPeriod :: FUML_Semantics_Extensions_Clock_Clock -> Int function_fUML_Clock_getPeriod c = let ccsls = function_fUML_parseCCSLs in let eventName = function_Event_NamedElement_name (function_Clock_LogicalClock_definingEvent c) ++ ";" in let physClk = filter (\c -> elem "physicalClk" c) ccsls in let eventClk = filter (\c -> elem eventName c) physClk in let ei = length eventClk == 1 in let c = head eventClk in if ei then let per = findPosA c "period" in let perv = init(takeUntil (\c -> c == ';') (c!!(per+1))) in if per < length c then str2int perv else 0 else 0 function_fUML_Clock_getPeriodWithDefault :: FUML_Semantics_Extensions_Clock_Clock -> Int function_fUML_Clock_getPeriodWithDefault c = let l = function_Clock_LogicalClock_locus(c) in let defaultPeriod = function_Locus_defaultPeriod2ReactionClk l in let reactionClk = function_Locus_reactionClock l in let period = function_fUML_Clock_getPeriod c in -- used to allow continuous behavior without explicit relationship with reactionClck if c == reactionClk && period == 0 then -- -1 defines that the edge for the evolution of physical clock is unlimited if defaultPeriod == -1 then 1 else defaultPeriod else period -- -- look for a CCSL that has physicalClk and the definingEvent function_fUML_Clock_isRelatedWithPhysicalClk :: FUML_Semantics_Extensions_Clock_Clock -> Bool function_fUML_Clock_isRelatedWithPhysicalClk c = if function_fUML_Clock_getPeriod c > 0 || function_Clock_LogicalClock_definingEvent c == function_Instance_Event_semanticEventForReactionClk then True else False -- -- look for a CCSL that has reactionClk and the definingEvent -- this patter is expected: -- c1 isCoarserThan reactionClk; c1 = PlantInRangeEvent; function_fUML_Clock_isRelatedWithReactionClk :: FUML_Semantics_Extensions_Clock_Clock -> Bool function_fUML_Clock_isRelatedWithReactionClk c = let ccsls = function_fUML_parseCCSLs in let eventName = function_Event_NamedElement_name (function_Clock_LogicalClock_definingEvent c) ++ ";" in let reactionClk = filter (\c -> elem "reactionClk;" c) ccsls in let eventClk = filter (\c -> elem eventName c) reactionClk in if length eventClk == 1 then True else False -- parse every CCSL in a set of words function_fUML_parseCCSLs :: [[String]] function_fUML_parseCCSLs = let cs = function_Constraint_InverseAppliedStereotype ClockConstraint in let vs = map (\c -> let vs = function_Constraint_specification c in let vt = function_ValueSpecification_type vs in if vs /= FUML_Syntax_Classes_Kernel_ValueSpecificationEmpty && vt == FUML_Syntax_Classes_Kernel_LiteralString then words (function_ValueSpecification_LiteralString_value vs) else [] ) (expr2list cs) in vs -- -- look for a CCSL that has idealCk and discretizedBy -- then reads the step(resolution) function_fUML_getResolutionPhysicalClk :: Float function_fUML_getResolutionPhysicalClk = let ccsls = function_fUML_parseCCSLs in let idealClk = filter (\c -> elem "idealClk" c) ccsls in let ei = length idealClk == 1 in let c = head idealClk in if ei then let dis = findPosA c "discretizedBy" in let step = init(takeUntil (\c -> c == ';') (c!!(dis+1))) in if dis < length c then function_fUML_StringToFloat step else 0.0 else 0.0 ------------------------------------------------------------------------------------------------------------------------------------------------------------ -- HELP FUNCTION -- function_fUML_StringToFloat :: String -> Float function_fUML_StringToFloat str = let strin = init(takeUntil (\c -> c == '.') (str)) in let strdec = tail(dropWhile (\c -> c /= '.') (str)) in primIntToFloat ( str2int strin ) + (primIntToFloat ( str2int strdec ) / (10.0^(length strdec))) -- -- find the position of a string in an array of strings findPosA :: [String] -> String -> Int findPosA list elem | head list == elem = 0 | otherwise = 1 + (findPosA (tail list) elem)